package com.aptemo.webetek.server.datastore;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import com.aptemo.webetek.client.enums.EnumBetStatus;
import com.aptemo.webetek.client.enums.EnumBetType;
import com.aptemo.webetek.client.enums.EnumEventStatus;
import com.aptemo.webetek.client.enums.EnumEventType;
import com.aptemo.webetek.client.enums.EnumPaymentOrdering;
import com.aptemo.webetek.client.enums.EnumPaymentType;
import com.aptemo.webetek.client.enums.EnumTeamOrdering;
import com.aptemo.webetek.client.enums.EnumUserOrdering;
import com.aptemo.webetek.client.enums.EnumUserRole;
import com.aptemo.webetek.client.enums.EnumUserStatus;
import com.aptemo.webetek.client.exceptions.BackendException;
import com.aptemo.webetek.shared.BetBean;
import com.aptemo.webetek.shared.EventBean;
import com.aptemo.webetek.shared.LabelBean;
import com.aptemo.webetek.shared.PagingResult;
import com.aptemo.webetek.shared.PaymentBean;
import com.aptemo.webetek.shared.PickBean;
import com.aptemo.webetek.shared.TeamBean;
import com.aptemo.webetek.shared.UserBean;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;

public class DataStoreCache implements DataStoreAPI
{

	private DataStoreAPI			decoree;

	private static final Logger		log				= Logger.getLogger(DataStoreCache.class.getName());

	private final MemcacheService	memcache		= MemcacheServiceFactory.getMemcacheService();

	private static final String		GAME_PREFIX		= "GAME/";
	private static final String		USER_PREFIX		= "USER/";
	private static final String		TEAM_PREFIX		= "TEAM/";
	private static final String		LABEL_PREFIX	= "LABEL/";
	private static final String		PAYMENT_PREFIX	= "PAYMENT/";
	private static final String		BET_PREFIX		= "BET/";
	private static final String		PICK_PREFIX		= "PICK/";

	private static final String		GAMES_PREFIX	= "GAMES/";
	private static final String		USERS_PREFIX	= "USERS/";
	private static final String		TEAMS_PREFIX	= "TEAMS/";
	private static final String		STATS_PREFIX	= "STATISTICS/";

	public DataStoreCache(DataStoreAPI decoree)
	{
		this.decoree = decoree;
	}

	@Override
	public EventBean getEvent(String gameId) throws BackendException
	{
		EventBean game = (EventBean) memcache.get(GAME_PREFIX + gameId);
		// no cache - go to datastore
		if (game == null)
		{
			game = decoree.getEvent(gameId);
			// store to cache...
			memcache.put(GAME_PREFIX + gameId, game);
		}
		return game;
	}

	@Override
	public List<EventBean> getEvents(String teamId, String labelId, Date treshold, EnumEventStatus enumBetStatus) throws BackendException
	{

		List<EventBean> games = (List<EventBean>) memcache.get(GAMES_PREFIX + teamId);
		// no cache - go to datastore
		// if (games == null)
		{
			games = decoree.getEvents(teamId, labelId, treshold, enumBetStatus);
			// store to cache...
			memcache.put(GAMES_PREFIX + teamId, games);
			// log.info("Cache missed!");
		}
		return games;
	}

	@Override
	public UserBean getPlayer(String userid) throws BackendException
	{
		UserBean user = (UserBean) memcache.get(USER_PREFIX + userid);
		// no cache - go to datastore
		if (user == null)
		{
			user = decoree.getPlayer(userid);
			// store to cache...
			memcache.put(USER_PREFIX + userid, user);
		}
		return user;
	}

	@Override
	public TeamBean getTeam(String teamId) throws BackendException
	{
		TeamBean team = (TeamBean) memcache.get(TEAM_PREFIX + teamId);
		// no cache - go to datastore
		if (team == null)
		{
			team = decoree.getTeam(teamId);
			// store to cache...
			memcache.put(TEAM_PREFIX + teamId, team);
		}
		return team;
	}

	@Override
	public boolean deleteEvent(String id) throws BackendException
	{
		memcache.delete(GAME_PREFIX + id);
		return decoree.deleteEvent(id);
	}

	@Override
	public boolean deletePlayer(String id) throws BackendException
	{
		memcache.delete(USER_PREFIX + id);
		return decoree.deletePlayer(id);
	}

	@Override
	public boolean deleteTeam(String id)
	{
		memcache.delete(TEAM_PREFIX + id);
		return decoree.deleteTeam(id);
	}

	@Override
	public EventBean modifyEvent(EventBean abet) throws BackendException
	{
		// memcache.put(GAME_PREFIX + abet.getKey(), abet);
		memcache.delete(GAME_PREFIX + abet.getKey());
		return decoree.modifyEvent(abet);
	}

	@Override
	public UserBean modifyPlayer(UserBean user) throws BackendException
	{
		memcache.delete(USER_PREFIX + user.getKey());
		return decoree.modifyPlayer(user);
	}

	@Override
	public TeamBean modifyTeam(TeamBean team) throws BackendException
	{
		memcache.delete(TEAM_PREFIX + team.getId());
		return decoree.modifyTeam(team);
	}

	@Override
	public EventBean createEvent(String teamid, String title, String description, Date date, List<PickBean> picks, EnumEventType type, String labelId)
			throws BackendException
	{
		// memcache.delete( PREFIX + teamid);
		return decoree.createEvent(teamid, title, description, date, picks, type, labelId);
	}

	@Override
	public PagingResult<EventBean> getEvents(String teamId, String labelId, Date treshold, EnumEventStatus enumBetStatus, String cursor, int pageSize)
			throws BackendException
	{
		// 
		return decoree.getEvents(teamId, labelId, treshold, enumBetStatus, cursor, pageSize);
	}

	@Override
	public PagingResult<BetBean> getBets(String teamId, String userId, EnumBetStatus status, String cursor, int pageSize) throws BackendException
	{
		return decoree.getBets(teamId, userId, status, cursor, pageSize);
	}

	@Override
	public PagingResult<UserBean> getPlayers(String teamId, EnumUserStatus status, EnumUserOrdering order, String cursor, int pageSize) throws BackendException
	{
		return decoree.getPlayers(teamId, status, order, cursor, pageSize);
	}

	@Override
	public PagingResult<PaymentBean> getPayments(String teamId, EnumPaymentType type, EnumPaymentOrdering order, String cursor, int pageSize)
			throws BackendException
	{
		return decoree.getPayments(teamId, type, order, cursor, pageSize);
	}

	@Override
	public UserBean createPlayer(String teamId, String email, EnumUserStatus status, EnumUserRole role, double initialBalance) throws BackendException
	{
		return decoree.createPlayer(teamId, email, status, role, initialBalance);
	}

	@Override
	public TeamBean createTeam(String name, String description, String teamRules, String ownerId, boolean publicity, boolean notifications, Double minStake,
			Double maxStake) throws BackendException
	{
		TeamBean bean = decoree.createTeam(name, description, teamRules, ownerId, publicity, notifications, minStake, maxStake);
		memcache.put(TEAM_PREFIX + bean.getId(), bean);
		return bean;
	}

	@Override
	public PagingResult<TeamBean> getTeams(String nameFilter, boolean publicity, EnumTeamOrdering order, String cursor, int pageSize) throws BackendException
	{
		return decoree.getTeams(nameFilter, publicity, order, cursor, pageSize);
	}

	@Override
	public List<PaymentBean> getPayments(String teamId, EnumPaymentType type, EnumPaymentOrdering order) throws BackendException
	{
		return decoree.getPayments(teamId, type, order);
	}

	@Override
	public List<UserBean> getPlayers(String teamId, EnumUserStatus status, EnumUserOrdering order) throws BackendException
	{
		return decoree.getPlayers(teamId, status, order);
	}

	@Override
	public PaymentBean createPayment(String userId, String teamId, double amount, EnumPaymentType type) throws BackendException
	{
		memcache.delete(USER_PREFIX + userId);
		PaymentBean bean = decoree.createPayment(userId, teamId, amount, type);
		// TODO cache bean...
		return bean;
	}

	@Override
	public BetBean getBet(String id) throws BackendException
	{
		BetBean bet = null;// (BetBean) memcache.get(BET_PREFIX + id);
		// no cache - go to datastore
		if (bet == null)
		{
			bet = decoree.getBet(id);
			// store to cache...
			memcache.put(BET_PREFIX + id, bet);
		}
		return bet;
	}

	@Override
	public List<BetBean> getBets(String userId, EnumBetStatus status) throws BackendException
	{
		return decoree.getBets(userId, status);
	}

	@Override
	public PaymentBean getPayment(String id) throws BackendException
	{
		PaymentBean payment = (PaymentBean) memcache.get(PAYMENT_PREFIX + id);
		// no cache - go to datastore
		if (payment == null)
		{
			payment = decoree.getPayment(id);
			// store to cache...
			memcache.put(PAYMENT_PREFIX + id, payment);
		}
		return payment;
	}

	@Override
	public List<TeamBean> getTeams(String nameFilter, boolean publicity, EnumTeamOrdering order) throws BackendException
	{
		return decoree.getTeams(nameFilter, publicity, order);
	}

	@Override
	public BetBean createBet(String userId, String teamId, double amount, List<String> pickKeys, EnumBetType betType) throws BackendException
	{
		return decoree.createBet(userId, teamId, amount, pickKeys, betType);
	}

	@Override
	public LabelBean createLabel(String teamId, String title) throws BackendException
	{
		return decoree.createLabel(teamId, title);
	}

	@Override
	public boolean deleteLabel(String id) throws BackendException
	{
		// 
		memcache.delete(LABEL_PREFIX + id);
		return decoree.deleteLabel(id);
	}

	@Override
	public List<LabelBean> getLabels(String teamId) throws BackendException
	{
		// 
		return decoree.getLabels(teamId);
	}

	@Override
	public LabelBean getLabel(String labelid) throws BackendException
	{
		// TODO Auto-generated method stub
		return decoree.getLabel(labelid);
	}

	@Override
	public LabelBean modifyLabel(LabelBean bean) throws BackendException
	{
		// TODO Auto-generated method stub
		return decoree.modifyLabel(bean);
	}

	@Override
	public List<String> getPicksForEvent(String userId, String betId) throws BackendException
	{
		return decoree.getPicksForEvent(userId, betId);
	}

	@Override
	public EventBean assignResultPick(String pickkey, String comment)
	{
		// memcache.delete(EVENT_PREFIX + id);
		return decoree.assignResultPick(pickkey, comment);
	}

	@Override
	public List<UserBean> completeStakes(String pickkey)
	{
		return decoree.completeStakes(pickkey);
	}

	@Override
	public boolean deletePayment(String id) throws BackendException
	{
		memcache.delete(PAYMENT_PREFIX + id);
		return decoree.deletePayment(id);
	}

	@Override
	public PickBean modifyPick(PickBean bean) throws BackendException
	{
		memcache.delete(PICK_PREFIX + bean.getId());
		return decoree.modifyPick(bean);
	}

	@Override
	public PickBean getPick(String id) throws BackendException
	{
		PickBean pick = (PickBean) memcache.get(PICK_PREFIX + id);
		// no cache - go to datastore
		if (pick == null)
		{
			pick = decoree.getPick(id);
			// store to cache...
			memcache.put(PICK_PREFIX + id, pick);
		}
		return pick;
	}

}
